import axios from 'axios';
import type {
  ScheduleCreate,
  ScheduleUpdate,
  ScheduleResponse,
  ScheduleDetailResponse,
  ScheduleList,
  ScheduleStats,
  ScheduleFilters,
  ScheduleParticipantResponse
} from '@/types/schedule';

import { API_BASE_URL } from './api';

export class ScheduleService {
  private static instance: ScheduleService;
  private api = axios.create({
    baseURL: `${API_BASE_URL}/api/v1/schedules`,
    timeout: 10000,
  });

  constructor() {
    this.setupInterceptors();
  }

  static getInstance(): ScheduleService {
    if (!ScheduleService.instance) {
      ScheduleService.instance = new ScheduleService();
    }
    return ScheduleService.instance;
  }

  private setupInterceptors() {
    this.api.interceptors.request.use((config) => {
      const token = localStorage.getItem('access_token');
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      return config;
    });

    this.api.interceptors.response.use(
      (response) => response,
      (error) => {
        if (error.response?.status === 401) {
          localStorage.removeItem('access_token');
          window.location.href = '/login';
        }
        return Promise.reject(error);
      }
    );
  }

  async createSchedule(data: ScheduleCreate): Promise<ScheduleResponse> {
    const response = await this.api.post<ScheduleResponse>('', data);
    return response.data;
  }

  async getSchedules(filters: ScheduleFilters = {}): Promise<ScheduleList> {
    const params = new URLSearchParams();
    
    Object.entries(filters).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        params.append(key, value.toString());
      }
    });

    const response = await this.api.get<ScheduleList>(`?${params.toString()}`);
    return response.data;
  }

  async getUpcomingSchedules(daysAhead: number = 7, memberId?: number | null): Promise<ScheduleResponse[]> {
    const params = new URLSearchParams();
    params.append('days_ahead', daysAhead.toString());
    
    if (memberId) {
      params.append('member_id', memberId.toString());
    }

    const response = await this.api.get<ScheduleResponse[]>(`/upcoming?${params.toString()}`);
    return response.data;
  }

  async getSchedulesByDateRange(startDate: string, endDate: string, memberId?: number | null): Promise<ScheduleResponse[]> {
    const params = new URLSearchParams();
    params.append('start_date', startDate);
    params.append('end_date', endDate);
    
    if (memberId) {
      params.append('member_id', memberId.toString());
    }

    const response = await this.api.get<ScheduleResponse[]>(`/by-date-range?${params.toString()}`);
    return response.data;
  }

  async getScheduleStats(startDate?: string | null, endDate?: string | null): Promise<ScheduleStats> {
    const params = new URLSearchParams();
    
    if (startDate) {
      params.append('start_date', startDate);
    }
    
    if (endDate) {
      params.append('end_date', endDate);
    }

    const response = await this.api.get<ScheduleStats>(`/stats?${params.toString()}`);
    return response.data;
  }

  async getSchedule(id: number): Promise<ScheduleDetailResponse> {
    const response = await this.api.get<ScheduleDetailResponse>(`/${id}`);
    return response.data;
  }

  async updateSchedule(id: number, data: ScheduleUpdate): Promise<ScheduleResponse> {
    const response = await this.api.put<ScheduleResponse>(`/${id}`, data);
    return response.data;
  }

  async deleteSchedule(id: number): Promise<void> {
    await this.api.delete(`/${id}`);
  }

  async getScheduleParticipants(scheduleId: number): Promise<ScheduleParticipantResponse[]> {
    const response = await this.api.get<ScheduleParticipantResponse[]>(`/${scheduleId}/participants`);
    return response.data;
  }

  async confirmScheduleParticipation(scheduleId: number, participantId: number): Promise<ScheduleParticipantResponse> {
    const response = await this.api.post<ScheduleParticipantResponse>(
      `/${scheduleId}/participants/${participantId}/confirm`
    );
    return response.data;
  }
}

export const scheduleService = ScheduleService.getInstance();